import java.io.IOException;

import javax.management.RuntimeErrorException;

public class Test {
    public static void main(String[] args) {
        catchException();
    }

    // 1、Exception存在继承关系
    // 2、catch捕获异常时，要先捕获子类异常，再捕获父类异常，否则编译器报错
    // 3、finally代码块总会被执行，可以用于资源释放等操作
    public static void catchException() {
        try {
            throwSomeExeption();
        } catch (InnerException e) {
            e.printStackTrace();
            System.out.println("捕获到InnerException");
        } catch (OuterException e) {
            e.printStackTrace();
            System.out.println("捕获到OuterException");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("捕获到Exception");
        } finally {
            System.out.println("执行finally代码块");
        }
        // 捕获多种异常
        // 如果某些异常的处理逻辑相同，但是异常本身不存在继承关系
        try {
            throwSomeExeption();
        } catch (RuntimeErrorException | IOException e) {
            e.printStackTrace();
            System.out.println("捕获到运行时异常或空指针异常");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("捕获到Exception");
        }
    }

    public static int throwSomeExeption() throws Exception {
        var rand = Math.random();
        if (rand < 0.2) {
            throw new OuterException("这是一个外层异常");
        } else if (rand < 0.4) {
            throw new InnerException("这是一个内层异常");
        } else if (rand < 0.6) {
            throw new Exception("这是一个通用异常");
        } else if (rand < 0.7) {
            throw new RuntimeErrorException(null, "这是一个运行时异常");
        } else if (rand < 0.8) {
            throw new IOException("这是一个IO异常");
        } else {
            return 1;
        }
    }
}

class OuterException extends Exception {
    public OuterException(String message) {
        super(message);
    }
}

class InnerException extends OuterException {
    public InnerException(String message) {
        super(message);
    }
}
// Throwable有两个体系：Error和Exception，Error表示严重的错误，程序无法处理，通常不捕获；Exception表示可以处理的异常
// Java规定：
// 必须捕获的异常，包括Exception及其子类，但不包括RuntimeException及其子类，这种类型的异常称为Checked Exception。
// 不需要捕获的异常，包括Error及其子类，RuntimeException及其子类。

// Java标准库定义的常用异常包括：
// Exception
// ├─ RuntimeException
// │ ├─ NullPointerException
// │ ├─ IndexOutOfBoundsException
// │ ├─ SecurityException
// │ └─ IllegalArgumentException
// │ └─ NumberFormatException
// ├─ IOException
// │ ├─ UnsupportedCharsetException
// │ ├─ FileNotFoundException
// │ └─ SocketException
// ├─ ParseException
// ├─ GeneralSecurityException
// ├─ SQLException
// └─ TimeoutException